]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
keyboard: Fix deleting the previous word
authorSebastian Keller <skeller@gnome.org>
Wed, 21 Feb 2024 14:20:24 +0000 (15:20 +0100)
committerCarlos Garnacho <carlosg@gnome.org>
Thu, 29 Feb 2024 14:56:16 +0000 (14:56 +0000)
Since mutter@33088d59 the cursor we receive from mutter already is a
character index while the code here still treated it like a byte offset.

Further the code to detect the previous word position was treating the
cursor parameter already like a character index, while passing the
cursor that was prior to that commit a byte offset.

The function also had some unreachable and redundant code paths. The
pos < 0 case can never be reached due to the max(). Also the regex
already ensures that all whitespace is considered, so the code to remove
spaces not actually do anything except when deleting the first word in
the text, in which it would cause the first character to not get
deleted.

Also it was not handling characters with more than 2 bytes correctly. In
the presence of these JS string functions, such as search(), can not be
considered to operate on character indices anymore but rather the number
of UTF-16 byte pairs. Issues with this can be avoided by using
iterators, which unlike anything else iterate on characters, not byte
pairs and by not using the results returned by JS string functions for
anything but JS strings.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2746>

js/ui/keyboard.js

index 1aa47ae47b52f250ac09f2335d81f2fbaf3f9244..180bc6b29417b07985a0e53ce5ab66e966b3d666 100644 (file)
@@ -1619,18 +1619,10 @@ export const Keyboard = GObject.registerClass({
     }
 
     _previousWordPosition(text, cursor) {
-        /* Skip word prior to cursor */
-        let pos = Math.max(0, text.slice(0, cursor).search(/\s+\S+\s*$/));
-        if (pos < 0)
-            return 0;
-
-        /* Skip contiguous spaces */
-        for (; pos >= 0; pos--) {
-            if (text.charAt(pos) !== ' ')
-                return GLib.utf8_strlen(text.slice(0, pos + 1), -1);
-        }
-
-        return 0;
+        const upToCursor = [...text].slice(0, cursor).join('');
+        const jsStringPos = Math.max(0, upToCursor.search(/\s+\S+\s*$/));
+        const charPos = GLib.utf8_strlen(text.slice(0, jsStringPos), -1);
+        return charPos;
     }
 
     _toggleDelete(enabled) {
@@ -1662,17 +1654,10 @@ export const Keyboard = GObject.registerClass({
                 if (cursor === 0)
                     return;
 
-                let encoder = new TextEncoder();
-                let decoder = new TextDecoder();
-
-                /* Find cursor/anchor position in characters */
-                const cursorIdx = GLib.utf8_strlen(decoder.decode(encoder.encode(
-                    text).slice(0, cursor)), -1);
-                const anchorIdx = this._timesDeleted < BACKSPACE_WORD_DELETE_THRESHOLD
-                    ? cursorIdx - 1
+                const anchor = this._timesDeleted < BACKSPACE_WORD_DELETE_THRESHOLD
+                    ? cursor - 1
                     : this._previousWordPosition(text, cursor);
-                /* Now get offset from cursor */
-                const offset = anchorIdx - cursorIdx;
+                const offset = anchor - cursor;
 
                 this._timesDeleted++;
                 Main.inputMethod.delete_surrounding(offset, Math.abs(offset));